package MTT::Libs::Report;

use Moose;

use utf8;

use POSIX qw(strftime);
use IO::File;
use Class::Date qw(date);
use Tie::IxHash;
use HTML::Table;
use MTT::Libs::Report::Writer;

use GD;
use GD::Graph;

has 'schema' => ( is => 'rw', required => 1 );

has result => ( is => 'rw' );
has result_file => ( is => 'rw' );
has file 	=> ( is => 'ro', default => sub { 
		($^O =~ /MSWin/i ? 'c:/Temp/r_' : '/tmp/r_') . int( rand 1000 ) }, lazy => 1 );

has graphics => ( is => 'ro', isa => 'ArrayRef', default => sub { [] } );
has graphic_data => ( is => 'rw', isa => 'HashRef', default => sub { {} } );

has rows => ( is => 'rw' );

has 'id' => ( is => 'rw' );
has 'name' => ( is => 'rw' );
has 'user' => ( is => 'rw' );
has 'date_create' => ( is => 'rw' );
has 'comment' => ( is => 'rw' );


has 'switches' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has 'trunks' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has 'companies' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has 'params' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has 'groups' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );

has dimension => ( is => 'rw' );

has group_fields => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );

has 'props' => ( is => 'rw', isa => 'HashRef' );

has report_dbh => ( is => 'rw' );
has sql => ( is => 'rw' );

has key_fields => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has date_fields => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has info_fields => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has param_fields => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
has cnn_key_fields => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );

has 'log' => ( is => 'ro', default => sub { Log::Log4perl->get_logger('All') } ); 


my @props = qw(date_from date_to report_type amask bmask short bi in out allcnn report_table graphic graphic_type);

use Data::Dumper;
use Log::Log4perl;

my %graphic_types = (
	LP => 'linespoints',
	L  => 'lines', 
	B  => 'bars', 
	B3D => 'bars3d', 
	A   => 'area', 
	P3D => 'pie3d', 
	H   => 'hbars', 
	L3D =>'lines3d'
);


my %group_map = (
	'Компания' => 't.company_name',
	'Город'	 => 't.city',
	'Регион' => 't.oblast',
	'Округ'	 => 't.fo',
	'Дата'	 => 'DATE(r.date)',
	'Время'  => 'DATE_FORMAT(r.date, "%H:00")',
	'Коммутатор' => 't.switch',
	'Тип коммутатора' => 't.type',
	'Назв. коммутатора' => 't.switch_name',
	'Код страны' => 'm.country_code'
);

my %head_map = (
	't.switch_name' => 'Коммутатор',
	't.company_name' => 'Компания',
	't.city' => 'Город',
	't.oblast' => 'Регион',
	't.fo' => 'Округ',
	'r.trunk' => 'Транк',
	't.switch' => 'Коммутатор',
	't.type' => 'Тип коммутатора',
	'DATE(r.date)' => 'Дата',
	'DATE_FORMAT(r.date, "%H:00")' => 'Время',
	'r.a_mask_in' => 'А код',
	'r.b_mask_in' => 'А код',
	'm.country_code' => 'Код страны',
	'm.country' => 'Страна',
	'm.city' => 'Город',
	'm.operator' => 'Оператор',
	'm.crc' => 'CRC32'
);


sub get_html {
	my ($self) = @_;

	my @header = $self->get_head();
#	unshift @header, 'N';

	my $n = 0;
#	foreach my $row ( @{ $self->result } ) {
#		$n++;
#		unshift @$row, $n;
#	}

	$self->rows( scalar( @{ $self->result } ) - 1 );

	my $table = HTML::Table->new(
#		-evenrowclass => 't0',
		-width => '99%',
		-head  => \@header,
		-class => 'result_table',
		-data  => $self->result
	);

#	$table->setRowStyle(1, 'background: #efeaef');
	$table->setBorder(1);
	$table->setCellSpacing(0);
	$table->setRowHead(1);

	my $rowspans = $self->{rowspans};
	my @rows = (2) x scalar( @$rowspans );
	foreach my $col (1..scalar(@$rowspans)) {
		foreach my $row ( @{ $rowspans->[$col] } ) {
			$table->setCellRowSpan($rows[$col], $col, $row);
			$rows[$col] += $row;
		}
	}

	return $table->getTable();
}


sub get_csv {
	my ($self) = @_;

	my $rw = MTT::Libs::Report::Writer::CSV->new(file => $self->file);
	$rw->init();
	$rw->add_page( undef, [ $self->get_head() ]);

	foreach my $row ( @{ $self->result } ) {
		$rw->add_row($row);
	}

	$rw->end_page();
	$rw->finish();

	return $self->file;
}

sub get_excel {
	my ($self) = @_;

	my $rw = MTT::Libs::Report::Writer::Excel->new(
		file => $self->file,
		colspan => scalar @{ $self->{rowspans} } - 2,
		rowspan => $self->{rowspans}->[0]->[0]
	);

	$rw->init();
	$rw->add_page( 'Отчет', [ $self->get_head() ] );

	foreach my $row ( @{ $self->result } ) {
		$rw->add_row($row);
	}

	$rw->end_page();
	$rw->finish();

	return $self->file;
}

sub make_report {
	my($self, $c) = @_;

	if ( $self->props->{report_type} =~ /cnn/ ) {
		$self->{is_cnn}	= $self->props->{report_type};
		$self->{is_cnn_all}	= $self->props->{allcnn};
	}
	$self->{is_mask} 	= 1 if $self->props->{report_table} ne 'trunk';
	$self->{is_short} 	= 1 if $self->props->{report_table} eq 'short';
	$self->{is_hour} 	= 1 if $self->props->{report_type} eq 'hour' || $self->{is_cnn};
	$self->{is_quarter} = 1 if $self->props->{report_type} eq 'quarter';


	my $groups = [];
	my %ge;
	if ( $self->{is_mask} ) {
		push @$groups, qw(m.country m.city m.operator), ( $self->{is_short} ? ('m.crc') : () ), qw(r.a_mask_in r.b_mask_in);
		%ge = map { $_ => 1 } @$groups;
	}

	foreach my $group ( @{ $self->groups } ) {
		push @$groups, 't.' . $group->compute;
	}

	$self->group_fields( $groups );

	my $data = $self->query( $c );
	my $rows_hash = $self->prepare($data);
	my ($result, $rowspans) = $self->transform($rows_hash);

	$self->result( $result );

	if ( $self->props->{graphics} ) {
		my $graphic_type = $graphic_types{ $self->props->{graphic_type} };
		$self->make_graphics($graphic_type);
	}

	$self->{rowspans} = $rowspans;
}	

sub get_graphic_data {
	my ($self) = @_;

	my $data = $self->result;
	return unless $data && $data->[0];

	my $cols = scalar @{ $data->[0] };
	my $param_idx = $cols - ( scalar @{ $self->param_fields } / $self->dimension );
	my $dir_idx	  = $param_idx - 1;
	my $date_idx  = $dir_idx - 2;
	my $trunk_idx = $date_idx - 1;

	my $pi = $param_idx;
	my (%p_i, %p_c);
	foreach ( @{ $self->param_fields } ) {
		/^([^_]+)/;
		$p_i{ $pi++ } = $1 unless $p_c{ $1 }++;
	}

	my (%result, $max_x, $max_y);
	foreach my $row ( @$data ) {
		foreach my $p ( $param_idx..$cols - 1 ) {
			push @{ $result{ $row->[$trunk_idx] }->{ $p_i{ $p } . '_' . $row->[ $dir_idx ] } }, $row->[ $p ] ;
		}
	}

	$self->graphic_data->{data} = \%result;
}

sub make_graphics {
	my ($self, $type) = @_;

	my $module = "GD::Graph::${type}";
	eval {
		require "$module"; 
	};
	if ( $@ ) {
		die "Cannot create graphic: $@";
	}

	$self->get_graphic_data();

	my $g = $module->new(400, 300) || die "Graphic error: $@";
	
	my $data = $self->graphic_data->{data};

	foreach my $trunk ( keys %$data ) {
		my @data;
		foreach my $sg ( keys %{ $data->{$trunk} } ) {
			push @data, $sg;
		}

		$g->set(
			x_label => 'XXX',
			y_label => 'YYY',
			title	=> 'Grafeg',
			y_max_value => 42,
			bgclr => 'white',
			transparent => 0
		);
	}

#	warn "----- 13 ----->>>\n", Dumper \%result;
#	warn "--- 42 --->>>\n" . Dumper \%p_i;

}

# Построение и выполнение SQL запроса
sub query {
	my ($self, $c) = @_;

	my $ci = $c->config->{StatDB}->{connect_info};
	my $dbh = DBI->connect(
		$ci->{dsn},
		$ci->{user},
		$ci->{password}
	) || die DBI->errstr;
	$dbh->do( $ci->{on_connect_do} );
	$dbh->{mysql_enable_utf8} = 1;

	$self->report_dbh($dbh);


	$self->key_fields( ['r.switch', 'r.trunk', 'r.date'] );
	$self->cnn_key_fields( ['r.switch', 'r.trunk'] );
	push @{ $self->cnn_key_fields }, 'r.date' unless $self->{is_cnn_all};
	
	# Определение таблиц
	my $report_table = 'report';

	if ( $self->{is_mask} ) {
		$report_table .= '_mask';
		if ( $self->{is_short} ) {
			$report_table .= '_short';
			push @{ $self->key_fields }, 'r.b_mask_out';
		}
	}
	else {
		$report_table .= '_trunk';
	}

	if ( $self->{is_hour} || $self->{is_cnn} ) {
		$report_table .= '_hour';
	}
	elsif ( $self->{is_quarter} ) {
		$report_table .= '_15min';
		push @{ $self->key_fields }, 'r.quarter';
	}

	my @tables;
	push @tables, 'trunks t';
	push @tables, 'masks m' if $self->{is_mask};

	
	# Поля, по которым группировать результат
	$self->info_fields( $self->group_fields );
	push @{ $self->info_fields }, 'r.trunk';
	if ( $self->{is_mask} ) {
	}

	push @{ $self->date_fields }, 'DATE(r.date)';
	if ( $self->{is_quarter} ) {
		push @{ $self->date_fields }, 'MAKETIME(HOUR(r.date), (r.quarter - 1) * 15, 0)';
	}
	else {
		push @{ $self->date_fields }, 'DATE_FORMAT(r.date, "%H:00")';
	}

#	$fields .= ', r.a_mask_in, r.a_mask_out, r.b_mask_in, r.b_mask_out' if $self->{is_mask};


	# Выбираемые поля
	if ( $self->{is_cnn} && !$self->props->{bi} ) {
		$self->props->{bi} = 1;
	}
	push @{ $self->param_fields }, map {
						( ( $self->{props}->{bi} ? $_->name . '_bi' : () ),
						  ( $self->{props}->{in} ? $_->name . '_in' : () ),
						  ( $self->{props}->{out} ? $_->name . '_out' : () )
						) }
						@{ $self->params };

	# Позиция BHLLOAD_bi, понадобится в случае ЧНН отчета
	if ( $self->{is_cnn} ) {
		my $bhl_pos = 0;
		foreach ( @{ $self->param_fields } ) {
			last if /BHLLOAD_bi/;
			$bhl_pos++;
		}

		unless ( $bhl_pos < scalar @{ $self->param_fields } ) {
			my @bhls = map { ( 
								( $self->{props}->{bi} ? "${_}_bi" : () ),
								( $self->{props}->{in} ? "${_}_in" : () ),
						  		( $self->{props}->{out} ? "${_}_out" : () )
						) }
						('BHLLOAD');
			push @{ $self->param_fields }, @bhls;

			my $param = $c->model('DBIC::Param')->search({name => 'BHLLOAD'})->next();
			push @{ $self->params }, $param if $param;

			$bhl_pos = scalar @{ $self->param_fields } - ( scalar(@bhls) ) + 1;
		}

		$self->{bhl_pos} = $bhl_pos;
	}

	# Условие 
	my @where;

	push @where, 'r.switch = t.switch AND r.trunk = t.trunk AND DATE(t.created) = DATE(r.date)';
	if ( $self->{is_mask} ) {
		if ( ! $self->{is_short} ) {
			push @where, 'm.mask = r.b_mask_in';
			if ( $self->props->{amask} ) {
				push @where, "(r.a_mask_in = '" . $self->props->{amask} . "' OR r.a_mask_out = '" . $self->props->{amask} . "')";
			}
			if ( $self->props->{bmask} ) {
				push @where, "(r.b_mask_in = '" . $self->props->{bmask} . "' OR r.b_mask_out = '" . $self->props->{bmask} . "')";
			}
		}
		else {
			push @where, 'm.crc = r.b_mask_in';
			if ( $self->props->{amask} ) {
				push @where, "(r.a_mask_in = '" . $self->props->{amask} . "' OR r.a_mask_out = '" . $self->props->{amask} . "')";
			}
			if ( $self->props->{bmask} ) {
				push @where, "(r.b_mask_in = '" . $self->props->{bmask} . "' OR r.b_mask_out = '" . $self->props->{bmask} . "')";
			}
		}
	}

	push @where, 'r.date >= "' . $self->props->{date_from} . '"' if $self->props->{date_from};
	push @where, 'r.date <= "' . $self->props->{date_to} . '"' if $self->props->{date_to};
	# Свичи
	push @where, 'r.switch IN (' . join(', ', map { "'" . $_->host_code . "'" } @{ $self->switches }) . ')';
	#транки
	push @where, 'r.trunk IN (' . join(', ', map { "'$_'" } @{ $self->trunks }) . ')' if @{ $self->trunks };
	#компании
	push @where, 't.company_name IN (' . join(', ', map { "'$_'" } @{ $self->companies }) . ')'
		if @{ $self->companies };

	# Сортировка
	my $order_by = join(', ', @{ $self->info_fields }); #'r.switch, r.trunk';
	$order_by .= ', ' . join(', ', @{ $self->key_fields });
	$order_by .= ', ' . join(', ', @{ $self->date_fields }) if @{ $self->date_fields };


	my $d1 = date( $self->props->{date_from} || strftime('%Y-%m-%d 00:00:00', localtime) );
	my $d2 = date( $self->props->{date_to} || strftime('%Y-%m-%d %H:%M:%S', localtime) );

	$Class::Date::DATE_FORMAT = '%Y-%m-%d';

	my @dates = ( $d1->string );
	while ( $d1->string ne $d2->string ) {
		$d1 += '1D';
		push @dates, $d1->string;
	}


	my %check_tbl;
	foreach ( @{ $self->report_dbh->selectall_arrayref('SHOW TABLES') } ) {
		next unless $_->[0] =~ /^(?:report).+(?:\d{4}_\d\d_\d\d)/;
		$check_tbl{ $_->[0] } = 1;
	}

	my @result;
	foreach my $d ( @dates ) {
		$d =~ s/-/_/g;
		my @tbls = @tables;
		my $table = $report_table . '_' . $d;

		push @tbls, $table . ' r';

		my $sql = 'SELECT ' 
				. join(', ', ( 
						join(', ', @{ $self->key_fields }),
						join(', ', @{ $self->info_fields }),
						join(', ', @{ $self->date_fields }),
						join(', ', @{ $self->param_fields })
					)
				)
				. ' FROM ' . join(', ', @tbls) 
				. ' WHERE ' . join(' AND ', @where) 
				. ' ORDER BY ' . $order_by;

		next unless $check_tbl{$table};

		my $sth = $dbh->prepare($sql);
		$sth->execute();

		while ( my $row = $sth->fetch() ) {
			push @result, [ @$row ]; 
		}

		if ( $dbh->err ) {
			$c->user_log->error( $dbh->errstr, 'report' );
		}
		else {
			$c->user_log->debug( $sql, 'report' );
		}
		
	}

	return \@result;
}


sub prepare {
	my ($self, $data) = @_;

	my %result;
	tie %result, 'Tie::IxHash';
	my $key_size = scalar @{ $self->key_fields };

	foreach my $row ( @$data ) {
		my @k_arr = splice(@$row, 0, $key_size);
		if ( $self->{is_cnn} ) {
			splice(@k_arr, scalar @{ $self->cnn_key_fields });
			$k_arr[-1] =~ s/\s+\d\d:\d\d:\d\d$// unless $self->{is_cnn_all};
		}
		my $key = join('_', @k_arr);
		push @{ $result{$key} }, $row;
	}

	if ( $self->{is_cnn} ) {
		my $bhl_pos = $self->{bhl_pos} + scalar @{ $self->{date_fields} } + scalar @{ $self->{info_fields} };

		foreach my $key ( keys %result ) {

			my @sort_rows = sort { $b->[$bhl_pos] <=> $a->[$bhl_pos] } @{ $result{$key} };
			if ( $self->{is_cnn} eq 'cnn' ) {
				$result{$key} = [ $sort_rows[0] ];
			}
			else {
				my $max = $sort_rows[0]->[$bhl_pos];
				my $mi = 0;
				for my $i ( 0..scalar(@sort_rows) - 1 ) {
					$mi = $i;
					last if $max != $sort_rows[$mi]->[$bhl_pos];
				}
				$result{$key} = [ $sort_rows[$mi] || $sort_rows[0] ];
			}
		}
	}

	return \%result;
}

# разбивает строки по bi, in, out (и определяет rowspan-ы)
sub transform {
	my ($self, $data) = @_;

	my $dirs = scalar grep { defined } ( $self->props->{bi}, $self->props->{in}, $self->props->{out} );
	$dirs = 3 unless $dirs;
	$self->dimension( $dirs );

	my $gn = scalar @{ $self->info_fields } + scalar @{ $self->date_fields };

	# Формирование табличного массива
	my (@result, @rowspans);
	foreach my $key ( keys %$data ) {

		foreach ( @{ $data->{$key} } ) {
			my @row = @$_;
#			splice(@row, 0, scalar @{ $self->key_fields });
			my @r = splice(@row, 0, $gn);
			my @rows;

			for (0..$dirs - 1) {
				push @{ $rows[$_] }, @r;
			}

			my ($yes_bi) = ($self->props->{bi} ? 1 : 0);
			my $in = $yes_bi; 
			my $out = $in + ( $self->props->{in} ? 1 : 0 );

			push @{ $rows[0] }, 'bi' if $self->props->{bi};
			push @{ $rows[$in] }, 'in' if $self->props->{in};
			push @{ $rows[$out] }, 'out' if $self->props->{out};

			my $n = 0;
			my $l = scalar @row;
			while ( $n < $l ) {
				for (0..$dirs - 1) {
					push @{ $rows[$_] }, shift @row;
				}
				$n += $dirs;
			}

			push @result, @rows;
		}
	}
#die Dumper(\@result);	

	my $spans = scalar( @{ $self->info_fields } )  + scalar( @{ $self->date_fields } );
	if ( $dirs > 1 ) {
		foreach (0..( int scalar(@result)/$dirs )) {
			foreach (0..$spans) {
				push @{ $rowspans[$_] }, $dirs;
			}
		}
	}

	$self->graphic_data->{data} = \@result;

	return wantarray ? (\@result, \@rowspans) : \@result;
}

sub get_head {
	my ($self) = @_;

	my @head;
	push @head, map { $_->name } @{ $self->groups };
	push @head, ('Транк');
	push @head, ('Дата', 'Время');
	push @head, 'Напр.';
	push @head, map { $_->descr } @{ $self->params };

	return @head;
}

sub process {
	my ($self, $p) = @_;

	$self->user( $p->{user} );
	$self->name( $p->{report_name} );
	$self->comment( $p->{comment} );

	delete $p->{user};

	warn Dumper($p);


	$self->props( {} );
	foreach my $prop (@props) { 
		$self->props->{$prop} = $p->{$prop} if $p->{$prop};
	}

	my $swids = $p->{'switches_do'};
	$swids = [ $swids ] unless ref $swids;
	my $switches = [];
	foreach my $id ( @$swids ) {
		my $switch = $self->schema->resultset('Switch')->find($id);
		push @$switches, $switch if $switch;
	}
	$self->switches( $switches );

	if ( my $trs = $p->{'trunks_do'} ) {
		$trs = [ $trs ] unless ref $trs;
		$self->trunks( $trs );
	}

	if ( my $comps = $p->{'companies_do'} ) {
		$comps = [ $comps ] unless ref $comps;
		$self->companies( $comps );
	}

	my $params = [];
	foreach my $name ( @{ $p->{'params_do'} } ) {
		my $param = $self->schema->resultset('Param')->search({name => $name})->next();
		push @$params, $param if $param;
	}
	$self->params( $params );

	my $groups = [];
	foreach my $name ( @{ $p->{groups_do} } ) {
		my $group = $self->schema->resultset('Param')->search({name => $name})->next();
		push @$groups, $group if $group;
	}
	$self->groups( $groups );

	return $self;
}

sub load {
	my ($self, $id_report) = @_;

	my $schema = $self->schema;
	my $report = $schema->resultset('Report')->find({
			id => $id_report
		});
	return unless $report;

	$self->id( $report->id );
	$self->name( $report->name );
	$self->user( $schema->resultset('User')->find( $report->id_user ) );
	$self->date_create( $report->date_create );
	$self->comment( $report->comment );

	my $store = $schema->resultset('ReportStore')->search({id_report => $report->id});

	$self->props( {} );
	foreach my $prop ( @props ) {
		if ( my $p = $store->find({id_report => $report->id, type => $prop}) ) {
			$self->props->{ $p->type } = $p->value;
		}
	}

	my ($switches, $trunks, $params, $groups, $companies) = ([], [], [], [], []);
	while ( my $param = $store->next() ) {
		if ( $param->type eq 'switch' ) {
		   	push @$switches, $self->schema->resultset('Switch')->find( $param->value );
	   	}
		elsif ( $param->type eq 'trunk' ) {
			push @$trunks, $param->value;
	   	}
		elsif ( $param->type eq 'company' ) {
			push @$companies, $param->value;
	   	}
	}

	foreach ( $schema->resultset('ReportParam')
						   ->search(
							   {
								   id_report => $report->id
							   },
							   {
								   order_by => 'number'
							   }
						   ) ) 
   	{
		
		my $param = $schema->resultset('Param')->find( $_->id_param->id );
		if ( $param ) {
			if ( $param->type == 0 ) {
				push @$params, $param;
			}
			else {
				push @$groups, $param;
			}
		}

	}

	$self->switches( $switches ) if @$switches;
	$self->params( $params ) if @$params;
	$self->groups( $groups ) if @$groups;
	$self->trunks( $trunks ) if @$trunks;
	$self->companies( $companies ) if @$companies;

	return $self;
}



sub save {
	my ($self) = @_;

	eval {
		$self->schema->txn_do( sub {

				my $report;
				my $schema = $self->schema;

				if ( $self->id ) {

					$report = $self->schema->resultset('Report')->find( $self->id );
					die "Report ${\( $self->id )} not found in storage" unless $report;

					$schema->resultset('ReportStore')
						   ->search({id_report => $self->id})
						   ->delete_all();

					$schema->resultset('ReportParam')
						   ->search({id_report => $self->id})
						   ->delete_all();


					$report->update({
							name => $self->name,
							comment => $self->comment,
							date_create => \'now()' 
							#strftime('%Y-%m-%d %H:%M:%S', localtime)
						});

				}
				else {

					$report = $schema->resultset('Report')->create({
							name => $self->name,
							id_user => $self->user->id,
							comment => $self->comment,
							date_create => \'now()'
							# strftime('%Y-%m-%d %H:%M:%S', localtime)
						});

					$self->id( $report->id );
				}

				my $number = 0;
				foreach my $param ( @{ $self->params } ) {
					$schema->resultset('ReportParam')->create({
							id_report => $report->id,
							id_param  => $param->id,
							number	  => ++$number
						}
					);
				}

				$number = 0;
				foreach my $group ( @{ $self->groups } ) {
					$schema->resultset('ReportParam')->create({
							id_report => $report->id,
							id_param  => $group->id,
							number	  => ++$number
						}
					);
				}

				my $store = $self->schema->resultset('ReportStore');

				foreach my $prop ( @props ) {
					$store->create({
							id_report => $report->id,
							type => $prop,
							value => $self->props->{$prop}
						}) if $self->props->{$prop};
				}

				my ($switches, $trunks, $params, $groups, $companies) = ([], [], [], [], []);

				if ( @{ $self->switches } ) {
					my $switch_ids = $self->switches;

					foreach ( @$switch_ids ) {
						$store->create({
								id_report => $report->id,
								type => 'switch',
								value => $_->id
							});

#						push @$switches, $self->schema->resultset('Switch')->find($id);
					}
				}

				if ( @{ $self->trunks } ) {
					my %exists;
					foreach my $tr ( @{ $self->trunks } ) {
						$store->create({
								id_report => $report->id,
								type => 'trunk',
								value => $tr
							}) unless $exists{$tr}++;
					}
				}

				if ( @{ $self->companies } ) {
					my %exists;
					foreach my $comp ( @{ $self->companies } ) {
						$store->create({
								id_report => $report->id,
								type => 'company',
								value => $comp
							}) unless $exists{$comp}++;
					}
				}

			}
		);
	};

	if ($@) {
		warn $@;
		if ( $@ =~ /Rollback failed/ ) {
			die 'somthing terrible has happened';
		}
		return 0;
	}

	return 1;
}



__PACKAGE__->meta->make_immutable;
1;
